package king.dominic.jlibrary.util;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.widget.ImageView;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * Created by king on 2017/4/19.
 * BitmapUtils
 */

public class BitmapUtils {
    private static final String TAG = "BitmapUtils";

    private BitmapUtils() {
    }

    //bitmap to byte[]
    public static byte[] toByteArray(final Bitmap bmp, final boolean needRecycle) {
        if (bmp == null) return null;
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        bmp.compress(Bitmap.CompressFormat.PNG, 100, output);
        if (needRecycle) {
            bmp.recycle();
        }

        byte[] result = output.toByteArray();
        try {
            output.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    public static String compress(String filePath, String dir) {
        try {
            File file = new File(filePath);
            byte[] bytes = compressBitmapToBytes(file.getPath(), 600, 0, 60, Bitmap.CompressFormat.JPEG);
            File jpg = new File(dir, CommonUtils.md5Encrypt(filePath) + "compress.jpg");
            FileUtils.writeByteArrayToFile(jpg, bytes);
            return jpg.getAbsolutePath();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static byte[] compressBitmapToBytes(String filePath, int reqWidth, int reqHeight, int quality, Bitmap.CompressFormat format) {
        Bitmap bitmap = getSmallBitmap(filePath, reqWidth, reqHeight);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(format, quality, baos);
        byte[] bytes = baos.toByteArray();
        bitmap.recycle();
        return bytes;
    }

    private static Bitmap getSmallBitmap(String filePath, int reqWidth, int reqHeight) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options);
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
        options.inJustDecodeBounds = false;
//      options.inPreferQualityOverSpeed = true;
        return BitmapFactory.decodeFile(filePath, options);
    }

    private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        int h = options.outHeight;
        int w = options.outWidth;
        int inSampleSize = 0;
        if (h > reqHeight || w > reqWidth) {
            float ratioW = (float) w / reqWidth;
            float ratioH = (float) h / reqHeight;
            inSampleSize = (int) Math.min(ratioH, ratioW);
        }
        inSampleSize = Math.max(1, inSampleSize);
        return inSampleSize;
    }

    public static Bitmap crop(Bitmap bitmap, Rect bounds) {
        return crop(bitmap, (int) bounds.left, (int) bounds.top, (int) bounds.right, (int) bounds.bottom);
    }

    public static Bitmap crop(Bitmap bitmap, int l, int t, int r, int b) {
        return Bitmap.createBitmap(bitmap, l, t, r - l, b - t);
    }

    public static Bitmap decodeYuvByteArray(byte[] data, int format, int width, int height) {
        return decodeYuvByteArray(data, format, width, height, 0, 0);
    }

    public static Bitmap decodeYuvByteArray(byte[] data, int format, int width, int height, int maxWidth, int maxHeight) {
        return decodeYuvByteArray(data, format, width, height, maxWidth, maxHeight, null);
    }

    public static Bitmap decodeYuvByteArray(byte[] data, int format, int width, int height, int maxWidth, int maxHeight, Rect bounds) {
        return decodeYuvByteArray(data, format, width, height, maxWidth, maxHeight, Bitmap.Config.ARGB_8888, bounds);
    }

    public static byte[] transformYuvByteArray(byte[] data, int format, int width, int height) {
        YuvImage yuvImage = new YuvImage(data, format, width, height, null);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        yuvImage.compressToJpeg(new Rect(0, 0, width, height), 100, baos);
        byte[] jpegData = baos.toByteArray();
        FileUtils.closeStreamAutoCatch(baos);
        return jpegData;
    }

    public static Bitmap decodeYuvByteArray(byte[] data, int format, int width, int height, int maxWidth, int maxHeight, Bitmap.Config toFormat, Rect bounds) {
        YuvImage yuvImage = new YuvImage(data, format, width, height, null);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        yuvImage.compressToJpeg(new Rect(0, 0, width, height), 100, baos);
        byte[] jpegData = baos.toByteArray();

        FileUtils.closeStreamAutoCatch(baos);

        BitmapFactory.Options opt = new BitmapFactory.Options();
        opt.inPreferredConfig = toFormat;

        if (maxWidth <= 0 && maxHeight <= 0)
            return BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, opt);

        opt.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, opt);
        opt.inSampleSize = maxWidth <= 0 ? opt.outHeight / maxHeight : (maxHeight <= 0 ? opt.outWidth / maxWidth : Math.max(opt.outHeight / maxHeight, opt.outWidth / maxWidth));
        opt.inSampleSize = opt.inSampleSize <= 0 ? 1 : opt.inSampleSize;

        opt.inJustDecodeBounds = false;

        if (bounds == null || bounds.width() <= 0 || bounds.height() <= 0)
            return BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, opt);
        Bitmap src = BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, opt);
        float scale = 1f * width / src.getWidth();
        Bitmap bitmap = BitmapUtils.crop(src, new Rect((int) (bounds.left / scale), (int) (bounds.top / scale), (int) (bounds.right / scale), (int) (bounds.bottom / scale)));
        src.recycle();
        return bitmap;
    }

    public static Bitmap decodeByteArray(byte[] data, int maxWidth, int maxHeight) {
        BitmapFactory.Options opt = new BitmapFactory.Options();
        opt.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(data, 0, data.length, opt);

        return null;
    }

    public static boolean saveImageViewToJpeg(ImageView imageView, File file) {
        if (!file.getParentFile().exists() && !file.getParentFile().mkdirs()) {
            LogUtil.e(TAG, "创建文件夹失败：" + file.getParentFile().getAbsolutePath());
            return false;
        }
        imageView.buildDrawingCache();
        Bitmap bitmap = imageView.getDrawingCache();
        BufferedOutputStream out = null;
        try {
            out = FileUtils.getOutputStream(file);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return false;
        } finally {
            FileUtils.closeStreamAutoCatch(out);
        }
        return true;
    }

    public static void compress(Bitmap bitmap, int quality, File file, int maxWidth) {
        float scale = 1f * maxWidth / bitmap.getWidth();
        scale = scale > 1 ? 1 : scale;
        Matrix m = new Matrix();
        m.setScale(scale, scale);
        Bitmap b = Bitmap.createBitmap(bitmap, 0, 0, (int) (bitmap.getWidth()), (int) (bitmap.getHeight()), m, true);
        BufferedOutputStream out = null;
        try {
            out = FileUtils.getOutputStream(file);
            b.compress(Bitmap.CompressFormat.JPEG, quality, out);
            b.recycle();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            FileUtils.closeStreamAutoCatch(out);
        }
    }

    public static Bitmap scale(Bitmap src, float scale, boolean isRecycleSrc) {
        int w = (int) (src.getWidth() * scale);
        int h = (int) (src.getHeight() * scale);
        Bitmap bitmap = Bitmap.createScaledBitmap(src, w, h, true);
        if (isRecycleSrc && !bitmap.equals(src)) src.recycle();
        return bitmap;
    }
}
